//===============================================================================
// Microsoft patterns & practices
// Web Client Software Factory
//-------------------------------------------------------------------------------
// Copyright (C) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//-------------------------------------------------------------------------------
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================
using System;
using System.Workflow.Runtime;
using WCSFContrib.PageFlow.WorkflowFoundation.Tests.Mocks;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace WCSFContrib.PageFlow.WorkflowFoundation.Tests
{
	[TestClass]
	public class WorkflowFoundationPageFlowFixture
	{
        [ClassInitialize]
        public static void SetupDatabase(TestContext testContext)
        {
            SetupDatabaseUtility.Setup();
        }

		[TestMethod]
		public void CanGetNameAndId()
		{
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(new MockNavigationService())
				)
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));

				Assert.AreNotEqual(Guid.Empty, pageFlow.Id);
				Assert.IsNotNull(pageFlow.Definition.Name);
				Assert.AreEqual("MockUnconstrainedPageFlow", pageFlow.Definition.Name);
			}
		}

		[TestMethod]
		public void CanEnumeratePages()
		{
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(new MockNavigationService())
				)
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));

				Assert.IsTrue(pageFlow.Definition.Pages.Contains(new Page("PageA", "~/PageA.aspx")));
				Assert.IsFalse(pageFlow.Definition.Pages.Contains(new Page("PageZ", "~/PageA.aspx")));
			}
		}

		[TestMethod]
		public void CanGetCurrentPage()
		{
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(new MockNavigationService())
				)
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));
				pageFlow.Start();
				Assert.IsNotNull(pageFlow.CurrentPage);
			}
		}

		[TestMethod]
		public void OnStartGoesToCurrentPage()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));

				pageFlow.Start();

				Assert.AreEqual("PageA", pageFlow.Definition.StartPage.Name);
				Assert.AreEqual("PageA", pageFlow.CurrentPage.Name);
			}
		}

		[TestMethod]
		public void CanRedirectToCurrentPageInUnconstrainedPageFlowIsTrue()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));

				pageFlow.Start();

				Assert.IsTrue(pageFlow.CanRedirectTo(pageFlow.CurrentPage.Name));
			}
		}

		[TestMethod]
		public void CanRedirectToCurrentPageInConstrainedPageFlowIsTrue()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockConstrainedPageFlow));

				pageFlow.Start();

				Assert.IsTrue(pageFlow.CanRedirectTo(pageFlow.CurrentPage.Name));
			}
		}

		[TestMethod]
		public void UnconstraintedPageFlowSendsUserBackJumping()
		{
			Assert.IsTrue(true);
		}

		[TestMethod]
		public void RedirectToCurrentPageInConstrainedPageFlowDoesNotChangeCurrentPage()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockConstrainedPageFlow));

				pageFlow.Start();

				string originalPage = pageFlow.CurrentPage.Name;
				pageFlow.SetCurrentPage(pageFlow.CurrentPage.Name);
				Assert.AreEqual(originalPage, pageFlow.CurrentPage.Name);
			}
		}

		[TestMethod]
		public void RedirectToCurrentPageInUnconstrainedPageFlowDoesNotChangeCurrentPage()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));

				pageFlow.Start();

				string originalPage = pageFlow.CurrentPage.Name;
				pageFlow.SetCurrentPage(pageFlow.CurrentPage.Name);
				Assert.AreEqual(originalPage, pageFlow.CurrentPage.Name);
			}
		}

		[TestMethod]
		[ExpectedException(typeof (NavigationException))]
		public void RedirectToAnotherPageInConstrainedPageFlowThrows()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockConstrainedPageFlow));

				pageFlow.Start();

				Assert.IsTrue(pageFlow.Definition.ContainsPage(new Page("PageB", "pageB.aspx")));
				pageFlow.SetCurrentPage("PageB");
			}
		}

		[TestMethod]
		[ExpectedException(typeof (NavigationException))]
		public void RedirectToNonExistingPageInConstrainedPageFlowThrows()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockConstrainedPageFlow));
				pageFlow.Start();

				Assert.IsFalse(pageFlow.Definition.ContainsPage(new Page("elsewhere", "elsewhere.aspx")));

				pageFlow.SetCurrentPage("elsewhere");
			}
		}

		[TestMethod]
		public void RedirectToAnotherPageInUnconstrainedPageFlowChangesCurrentPageToTarget()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));

				pageFlow.Start();
				pageFlow.SetCurrentPage("PageB");

				Assert.AreEqual("PageB", pageFlow.CurrentPage.Name);
			}
		}

		[TestMethod]
		public void ShouldDeletePageFlowInstanceAndRedirectToCancelUrlOnTerminate()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));

				pageFlow.Start();
				pageFlow.Abort(true);

				Assert.AreEqual(pageFlow.Definition.AbortPage, navigationService.LastRequestedPage);
			}
		}

		[TestMethod]
		public void PageflowShouldCleanUpOnAbort()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
				Guid id = pageFlow.Id;

				pageFlow.Start();
				pageFlow.Abort(true);

				try
				{
					WorkflowFoundationPageFlow pf = (WorkflowFoundationPageFlow)factory.GetPageFlow(typeof(MockUnconstrainedPageFlow), id);

					Assert.AreEqual(PageFlowStatus.Terminated, pf.Status);
				}
				catch (InvalidOperationException ex)
				{
					Assert.IsTrue(ex.Message.Contains(id.ToString()));
					return;
				}
				Assert.Fail("Wrong exception or no exception thrown");
			}

			
		}

		[TestMethod]
		public void ShouldDeletePageFlowInstanceAndNotRedirectToCancelUrlOnTerminate()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));
				pageFlow.Start();

				navigationService.LastRequestedPage = null;

				pageFlow.Abort(false);

				Assert.IsNull(navigationService.LastRequestedPage);
			}
		}

		[TestMethod]
		public void CanQueryPageFlowStatus()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));
				Assert.AreEqual(PageFlowStatus.NotStarted, pageFlow.Status);

				pageFlow.Start();
				Assert.AreEqual(PageFlowStatus.Running, pageFlow.Status);

				pageFlow.Abort(false);
				Assert.AreEqual(PageFlowStatus.Terminated, pageFlow.Status);                
			}
		}

		[TestMethod]
		public void ShouldExposeWorkflowFoundationInstance()
		{
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(new MockNavigationService())
				)
			{
				WorkflowFoundationPageFlow pageFlow =
					(WorkflowFoundationPageFlow) factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));

				Assert.IsNotNull(pageFlow.WorkflowInstance);
				Assert.IsTrue(pageFlow.WorkflowInstance is WorkflowInstance);
			}
		}

		[TestMethod]
		public void ShouldRedirectToCurrentPage()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));
				pageFlow.Start();
				navigationService.LastRequestedPage = null;
				pageFlow.RedirectToCurrentPage();

				Assert.AreEqual(pageFlow.CurrentPage, navigationService.LastRequestedPage);
			}
		}

		[TestMethod]
		public void CanQueryPagesOnPageFlow()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));

				Assert.AreEqual(pageFlow.Definition.Pages[0].Name, "PageA");
				Assert.AreEqual(pageFlow.Definition.Pages.Count,
				                Activator.CreateInstance<MockUnconstrainedPageFlow>().Activities.Count);
			}
		}

		[TestMethod]
		public void CanQueryStartPage()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));

				Assert.IsNotNull(pageFlow.Definition.StartPage.Name,
				                 Activator.CreateInstance<MockUnconstrainedPageFlow>().InitialStateName);
			}
		}

		[TestMethod]
		public void UserCanQueryAboutPosibleTransitionsOnPageFlow()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));
				pageFlow.Start();
				Assert.AreEqual(1, pageFlow.Transitions.Count);
				Assert.IsNotNull(pageFlow.Transitions[0]);
			}
		}

		[TestMethod]
		public void PageFlowFiresStartedEventOnStart()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));
				TestEventHandler<PageFlowEventArgs> handler = new TestEventHandler<PageFlowEventArgs>();
				pageFlow.Started += new EventHandler<PageFlowEventArgs>(handler.HandleEvent);
				pageFlow.Start();

				Assert.AreEqual(handler.EventArgs.PageFlow, pageFlow);
				Assert.AreEqual(1, handler.FireCount);
			}
		}

		[TestMethod]
		public void PageFlowFiresAbortedEventOnStart()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));
				TestEventHandler<PageFlowAbortedEventArgs> handler = new TestEventHandler<PageFlowAbortedEventArgs>();
				pageFlow.Aborted += new EventHandler<PageFlowAbortedEventArgs>(handler.HandleEvent);
				pageFlow.Start();
				pageFlow.Abort(false);

				Assert.AreEqual(handler.EventArgs.AbortedPageFlowId, pageFlow.Id);
				Assert.AreEqual(1, handler.FireCount);
			}
		}

		[TestMethod]
		public void ShouldGetPageFlowDeclaringType()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));

				Assert.AreEqual(typeof (MockUnconstrainedPageFlow), pageFlow.Definition.PageFlowType);
			}
		}

		[TestMethod]
		public void ShouldPassDataToPageFlowAndViceversa()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));

				pageFlow.Start();
				pageFlow.UserData["myPageFlowData"] = 1;

				Assert.IsNotNull(pageFlow.UserData["myPageFlowData"]);
				Assert.AreEqual(1, pageFlow.UserData["myPageFlowData"]);
			}
		}


		[TestMethod]
		public void ShouldDisposeUserData()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));

				pageFlow.Start();
				pageFlow.UserData["myPageFlowData"] = 1;
				pageFlow.UserData.Remove("myPageFlowData");
				Assert.IsFalse(pageFlow.UserData.Contains("myPageFlowData"));
			}
		}

		[TestMethod]
		[ExpectedException(typeof (ArgumentException))]
		public void ShouldThrowIfNotExists()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));

				pageFlow.Start();

				string value = (string) pageFlow.UserData["notExistingSlot"];
				Assert.IsNull(value);
			}
		}

		[TestMethod]
		public void ShouldReturnKeys()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));

				pageFlow.Start();

				int initialCount = pageFlow.UserData.Keys.Count;

				pageFlow.UserData["a"] = 0;
				pageFlow.UserData["b"] = 0;
				pageFlow.UserData["c"] = 0;

				Assert.AreEqual(initialCount + 3, pageFlow.UserData.Keys.Count);
			}
		}

		[TestMethod]
		public void ShouldTestWhetherContainsStateSlot()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));

				pageFlow.Start();

				pageFlow.UserData["MockSlot01"] = 0;

				Assert.IsTrue(pageFlow.UserData.Contains("MockSlot01"));
				Assert.IsFalse(pageFlow.UserData.Contains("MockSlot02"));
			}
		}

		[TestMethod]
		[ExpectedException(typeof (ArgumentNullException))]
		public void SetStateSlotKeyCannotBeNullOrEmpty()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));

				pageFlow.Start();

				pageFlow.UserData[string.Empty] = 0;
			}
		}

		[TestMethod]
		[ExpectedException(typeof (ArgumentNullException))]
		public void GetStateSlotKeyCannotBeNullOrEmpty()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));

				pageFlow.Start();

				object value = pageFlow.UserData[string.Empty];

				Assert.IsNull(value);
			}
		}

		[TestMethod]
		[ExpectedException(typeof (ArgumentNullException))]
		public void ContainsStateSlotKeyCannotBeNullOrEmpty()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));

				pageFlow.Start();

				pageFlow.UserData.Contains(null);
			}
		}

		[TestMethod]
		[ExpectedException(typeof (ArgumentNullException))]
		public void RemoveStateSlotKeyCannotBeNullOrEmpty()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));

				pageFlow.Start();

				pageFlow.UserData.Remove(string.Empty);
			}
		}

		[TestMethod]
		public void ShouldCanRedirectToBeFalseIfPageFlowIsConstrainedAndCurrentPageIsDiffrentFromRequestedOne()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockConstrainedPageFlow));
				pageFlow.Start();
				bool canRedirect = pageFlow.CanRedirectTo("PageB");

				Assert.IsFalse(canRedirect);
			}
		}

		[TestMethod]
		public void ShouldCanRedirectToBeTrueIfPageFlowIsUnconstrainedAndCurrentPageIsDiffrentFromRequestedOne()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));
				pageFlow.Start();
				bool canRedirect = pageFlow.CanRedirectTo("PageB");

				Assert.IsTrue(canRedirect);
			}
		}

		[TestMethod]
		public void DataIsNotSharedAcrossInstances()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow instanceA = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));
				instanceA.Start();
				instanceA.UserData["CustomerStatus"] = "green";

				IPageFlow instanceB = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));
				instanceB.Start();

				Assert.IsNotNull(instanceA.UserData["CustomerStatus"]);
				Assert.AreEqual("green", instanceA.UserData["CustomerStatus"]);
				Assert.IsFalse(instanceB.UserData.Contains("CustomerStatus"));
			}
		}

		[TestMethod]
		public void DevCanSuspendPageFlow()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));
				pageFlow.Start();
				pageFlow.Suspend();

				Assert.AreEqual(PageFlowStatus.Suspended, pageFlow.Status);
			}
		}

        [TestMethod]
        public void DevCanResumePageFlow()
        {
            MockNavigationService navigationService = new MockNavigationService();
            using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();
                pageFlow.Suspend();
                pageFlow.Resume();

                Assert.AreEqual(PageFlowStatus.Running, pageFlow.Status);
            }
        }

		[TestMethod]
		public void PageFlowFiresSuspendedEventOnSuspend()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));
				pageFlow.Start();
				TestEventHandler<PageFlowEventArgs> handler = new TestEventHandler<PageFlowEventArgs>();
				pageFlow.Suspended += new EventHandler<PageFlowEventArgs>(handler.HandleEvent);
				pageFlow.Suspend();

				Assert.AreEqual(1, handler.FireCount);
				Assert.AreEqual(pageFlow, handler.EventArgs.PageFlow);
			}
		}

        [TestMethod]
        public void PageFlowFiresResumedEventOnResume()
        {
            MockNavigationService navigationService = new MockNavigationService();
            using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();
                pageFlow.Suspend();
                TestEventHandler<PageFlowEventArgs> handler = new TestEventHandler<PageFlowEventArgs>();
                pageFlow.Resumed += new EventHandler<PageFlowEventArgs>(handler.HandleEvent);
                pageFlow.Resume();

                
                Assert.AreEqual(1, handler.FireCount);
                Assert.AreEqual(pageFlow, handler.EventArgs.PageFlow);
            }
        }

		[TestMethod]
		public void ShouldNotRedirectUserWhenSuspending()
		{
			MockNavigationService navigationService = new MockNavigationService();
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
				pageFlow.Start();
				
				//clear the navigation
				navigationService.LastRequestedPage = null;
				
				pageFlow.Suspend();

				Assert.IsNull(navigationService.LastRequestedPage);
			}
		}

		[TestMethod]
		public void ShouldKeepStateWhenSuspendingAndResuming()
		{
			MockNavigationService navigationService = new MockNavigationService();
			Guid pageFlowId;
			Page preSuspendPage;
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));
				pageFlow.Start();
				pageFlowId = pageFlow.Id;
				pageFlow.UserData["something"] = 1;
				pageFlow.Navigate("Next");
				preSuspendPage = pageFlow.CurrentPage;
				pageFlow.Suspend();
			}

			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(navigationService))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow), pageFlowId);
                pageFlow.Resume();

				Assert.AreEqual(preSuspendPage, pageFlow.CurrentPage);
				Assert.AreEqual(1, pageFlow.UserData["something"]);
				Assert.AreEqual(PageFlowStatus.Running, pageFlow.Status);
			}
		}
		
		[TestMethod]
		public void ShouldReplaceExisitingSlotWithNewData()
		{
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(new MockNavigationService()))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
				pageFlow.Start();

				pageFlow.UserData["slot"] = 1;
				pageFlow.UserData["slot"] = 5;
				
				Assert.AreEqual(5, (int)pageFlow.UserData["slot"]);
			}
		}

		[TestMethod]
		[ExpectedException(typeof (ArgumentNullException))]
		public void WorkflowInstanceCannotBeNull()
		{
			new WorkflowFoundationPageFlow(null, new MockNavigationService(), null);
		}

		[TestMethod]
		public void ShouldExecuteNamedTransitions()
		{
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(new MockNavigationService())
				)
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockConstrainedPageFlow));
				pageFlow.Start();
				pageFlow.Navigate("goToB");
				Assert.AreEqual("PageB", pageFlow.CurrentPage.Name);
			}
		}

		[TestMethod]
		public void NamedTransitionsShouldBeCaseInsensitive()
		{
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(new MockNavigationService())
				)
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockConstrainedPageFlow));
				pageFlow.Start();
				pageFlow.Navigate("gotob");
				Assert.AreEqual("PageB", pageFlow.CurrentPage.Name);
			}
		}

		[TestMethod]
		public void ShouldExecuteDefaultTransitions()
		{
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(new MockNavigationService())
				)
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockConstrainedPageFlow));
				pageFlow.Start();
				pageFlow.Next();
				Assert.AreEqual("PageC", pageFlow.CurrentPage.Name);
			}
		}

		[TestMethod]
		[ExpectedException(typeof (NavigationException))]
		public void ShouldThrowNavigationExceptionIsTransitionDoesntExists()
		{
			using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(new MockNavigationService())
				)
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockConstrainedPageFlow));
				pageFlow.Start();
				pageFlow.Navigate("nonExistingTransition");
			}
		}
		
		[TestMethod]
		public void ShouldMarkPageFlowAsNotRunningAndFireCompletedEvent()
		{
			using(WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(new MockNavigationService()))
			{
				IPageFlow pageFlow = factory.GetPageFlow(typeof (MockUnconstrainedPageFlow));
				pageFlow.Start();
				TestEventHandler<PageFlowEventArgs> handler = new TestEventHandler<PageFlowEventArgs>();
				pageFlow.Completed += new EventHandler<PageFlowEventArgs>(handler.HandleEvent);
				pageFlow.Complete();
				
				
				Assert.AreEqual(1, handler.FireCount);
				Assert.AreEqual(pageFlow, handler.EventArgs.PageFlow);
				Assert.AreEqual(PageFlowStatus.Terminated, pageFlow.Status);
			}
		}

        [TestMethod]
        public void MantainStatusWhenCreatingSamePageFlowInDifferentRequests()
        {
            using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(new MockNavigationService()))
            {
                // 1st request
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();
                pageFlow.Suspend();
                
                Assert.AreEqual(PageFlowStatus.Suspended, pageFlow.Status);

                // 2nd request
                IPageFlow pageFlow2 = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow), pageFlow.Id);
                
                Assert.AreEqual(PageFlowStatus.Suspended, pageFlow2.Status);
                
            }
        }

        [TestMethod]
        public void MantainStatusWhenCreatingSamePageFlowInDifferentRequests2()
        {
            using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(new MockNavigationService()))
            {
                // 1st request
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                
                Assert.AreEqual(PageFlowStatus.NotStarted, pageFlow.Status);

                // 2nd request
                IPageFlow pageFlow2 = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow), pageFlow.Id);
                pageFlow2.Start();
                
                Assert.AreEqual(PageFlowStatus.Running, pageFlow2.Status);

            }
        }

        [TestMethod]
        [ExpectedException(typeof(PageFlowException))]
        public void SuspendBeforeStartThrows()
        {
            using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Suspend();                
            }
        }

        [TestMethod]
        [ExpectedException(typeof(PageFlowException))]
        public void ResumeBeforeStartThrows()
        {
            using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Resume();
            }
        }

        [TestMethod]
        [ExpectedException(typeof(PageFlowException))]
        public void AbortBeforeStartThrows()
        {
            using (WorkflowFoundationPageFlowFactory factory = new WorkflowFoundationPageFlowFactory(new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Abort(false);
            }
        }
	}
}
